From 5742005aa164bdd5cf9e5b05358085d6a8895ad7 Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Sat, 7 Feb 2009 18:46:31 +0100 Subject: [PATCH] Make outstanding window moves work with the new model We now copy outstanding window moves directly on the window and not to an intermediary pixmap, this means our previous code to combine window copies was wrong (it relied on each copy not destroying the source date). Furthermore, we can't just remove all the update area from the destination of the outstanding moves, as sometimes things get copied into that area and then used as the source of another copy. We replace the previous window copy combining with a naive version that just queues each move, just to get things right. Further work to optimize copies is possible. Also, we don't remove copy destinations that are used as source for later copies. We also clean up the memory management by not having move_region_on_impl taking ownership of the passed in region. --- gdk/gdkwindow.c | 96 +++++++++++++++++-------------------------------- 1 file changed, 33 insertions(+), 63 deletions(-) diff --git a/gdk/gdkwindow.c b/gdk/gdkwindow.c index 5aeb9ef71d..d8ced4d005 100644 --- a/gdk/gdkwindow.c +++ b/gdk/gdkwindow.c @@ -2219,10 +2219,25 @@ gdk_window_begin_paint_region (GdkWindow *window, gdk_region_union (implicit_paint->region, paint->region); /* No need to do any moves that will end up over the exposed area */ - for (l = impl_window->outstanding_moves; l != NULL; l = l->next) + if (impl_window->outstanding_moves) { - move = l->data; - gdk_region_subtract (move->region, paint->region); + GdkRegion *remove; + + remove = gdk_region_copy (paint->region); + for (l = g_list_last (impl_window->outstanding_moves); l != NULL; l = l->prev) + { + move = l->data; + /* Don't need this area */ + gdk_region_subtract (move->region, remove); + + /* However if any of the destination we do need has a source + in the updated region we do need that as a destination for + the earlier moves */ + gdk_region_offset (move->region, -move->dx, -move->dy); + gdk_region_subtract (remove, move->region); + gdk_region_offset (move->region, move->dx, move->dy); + } + gdk_region_destroy (remove); } /* Convert back to normal coords */ @@ -2521,79 +2536,33 @@ append_move_region (GdkWindowObject *impl_window, GdkRegion *region, int dx, int dy) { - GList *moves_to_add, *l, *s; - GdkRegion *intersection; - GdkWindowRegionMove *move, *new_move, *existing_move; - + GdkWindowRegionMove *move; + move = g_slice_new (GdkWindowRegionMove); - move->region = region; + move->region = gdk_region_copy (region); move->dx = dx; move->dy = dy; - moves_to_add = g_list_prepend (NULL, move); - - for (l = impl_window->outstanding_moves; l != NULL; l = l->next) - { - existing_move = l->data; - - for (s = moves_to_add; s != NULL; s = s->next) - { - move = s->data; - - intersection = gdk_region_copy (move->region); - gdk_region_offset (intersection, -move->dx, -move->dy); - gdk_region_intersect (intersection, existing_move->region); - gdk_region_offset (intersection, move->dx, move->dy); - - if (!gdk_region_empty (intersection)) - { - - new_move = g_slice_new (GdkWindowRegionMove); - new_move->region = intersection; - new_move->dx = move->dx + existing_move->dx; - new_move->dy = move->dy + existing_move->dy; - moves_to_add = g_list_prepend (moves_to_add, new_move); - - gdk_region_subtract (move->region, intersection); - gdk_region_subtract (existing_move->region, intersection); - } - else - gdk_region_destroy (intersection); - } - } - - impl_window->outstanding_moves = g_list_concat (impl_window->outstanding_moves, - moves_to_add); - + impl_window->outstanding_moves = + g_list_prepend (impl_window->outstanding_moves, move); } -/* Moves bits and update area by dx/dy in impl window - * Takes ownership of region. - */ +/* Moves bits and update area by dx/dy in impl window */ static void move_region_on_impl (GdkWindowObject *private, GdkRegion *region, /* In impl window coords */ int dx, int dy) { GdkWindowObject *impl_window; - gboolean free_region; if ((dx == 0 && dy == 0) || gdk_region_empty (region)) - { - gdk_region_destroy (region); - return; - } + return; - free_region = TRUE; impl_window = gdk_window_get_impl_window (private); if (1) /* Enable flicker free handling of moves. */ - { - free_region = FALSE; - - append_move_region (impl_window, region, dx, dy); - } + append_move_region (impl_window, region, dx, dy); else do_move_region_bits_on_impl (private, region, dx, dy); @@ -2608,14 +2577,12 @@ move_region_on_impl (GdkWindowObject *private, gdk_region_offset (update_area, -dx, -dy); gdk_region_intersect (update_area, impl_window->update_area); gdk_region_subtract (impl_window->update_area, update_area); + /* Convert back */ gdk_region_offset (update_area, dx, dy); gdk_region_union (impl_window->update_area, update_area); gdk_region_destroy (update_area); } - - if (free_region) - gdk_region_destroy (region); } /* Flushes all outstanding changes to the window, call this @@ -6221,7 +6188,7 @@ gdk_window_move_resize_internal (GdkWindow *window, /* convert from parent coords to impl */ gdk_region_offset (copy_area, private->abs_x - private->x, private->abs_y - private->y); - move_region_on_impl (private, copy_area, dx, dy); /* Takes ownership of copy_area */ + move_region_on_impl (private, copy_area, dx, dy); /* Invalidate affected part in the parent window * (no higher window should be affected) @@ -6232,6 +6199,7 @@ gdk_window_move_resize_internal (GdkWindow *window, gdk_region_destroy (old_region); gdk_region_destroy (new_region); + gdk_region_destroy (copy_area); } if (old_native_child_region) @@ -6427,11 +6395,12 @@ gdk_window_scroll (GdkWindow *window, /* convert from window coords to impl */ gdk_region_offset (copy_area, private->abs_x, private->abs_y); - move_region_on_impl (private, copy_area, dx, dy); /* Takes ownership of copy_area */ + move_region_on_impl (private, copy_area, dx, dy); /* Invalidate not copied regions */ gdk_window_invalidate_region (window, noncopy_area, TRUE); + gdk_region_destroy (copy_area); gdk_region_destroy (noncopy_area); if (old_native_child_region) @@ -6504,8 +6473,9 @@ gdk_window_move_region (GdkWindow *window, /* convert from window coords to impl */ gdk_region_offset (copy_area, private->abs_x, private->abs_y); - move_region_on_impl (private, copy_area, dx, dy); /* Takes ownership of copy_area */ + move_region_on_impl (private, copy_area, dx, dy); + gdk_region_destroy (copy_area); gdk_region_destroy (source_area); } -- 2.30.2